package com.k2data.k2app.service;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.k2data.k2app.common.OrikaMapperFactory;
import com.k2data.k2app.constant.Constant;
import com.k2data.k2app.domain.DeviceCond;
import com.k2data.k2app.domain.DeviceDTO;
import com.k2data.k2app.domain.po.SusbTimeIndex;
import com.k2data.k2app.mapper.SusbTimeIndexMapper;
import com.k2data.k2app.utils.DateFormatterUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Created by k2data on 17-11-14.
 */
@Service
public class SusbTimeIndexService {

    @Autowired
    private DeviceService deviceService;

    private final SusbTimeIndexMapper susbTimeIndexMapper;

    @Autowired
    public SusbTimeIndexService (SusbTimeIndexMapper susbTimeIndexMapper) {
        this.susbTimeIndexMapper = susbTimeIndexMapper;
    }

    public Map<Integer,Map<Integer, Map>> selectSusbGroupYear(Long customerId,Long deviceId,List<String> years){
        String yearStr = years.stream().collect(Collectors.joining(","));
        // 查询改年启停状态区间
        List<SusbTimeIndex> susbTimeIndicesFirst1 = susbTimeIndexMapper.selectSusbByCustomer(customerId,deviceId,yearStr);
        List<SusbTimeIndex> susbTimeIndicesFirst = Lists.newArrayList();
        //去除启停机重复启启停停的数据
        if(!susbTimeIndicesFirst1.isEmpty()){
            ZonedDateTime startN1 = susbTimeIndicesFirst1.get(0).getStartTime().plusHours(8L);
            ZonedDateTime stopN1 = susbTimeIndicesFirst1.get(0).getStopTime().plusHours(8L);
            susbTimeIndicesFirst1.get(0).setStartTime(startN1);
            susbTimeIndicesFirst1.get(0).setStopTime(stopN1);
            susbTimeIndicesFirst.add(susbTimeIndicesFirst1.get(0));
            for (int i=1;i<susbTimeIndicesFirst1.size();i++ ) {
                if(!susbTimeIndicesFirst1.get(i).getType().equals(susbTimeIndicesFirst1.get(i-1).getType())){
                    //数据库存储的是0时区数据，此处加8小时
                    ZonedDateTime startN = susbTimeIndicesFirst1.get(i).getStartTime().plusHours(8L);
                    ZonedDateTime stopN = susbTimeIndicesFirst1.get(i).getStopTime().plusHours(8L);
                    susbTimeIndicesFirst1.get(i).setStartTime(startN);
                    susbTimeIndicesFirst1.get(i).setStopTime(stopN);
                    susbTimeIndicesFirst.add(susbTimeIndicesFirst1.get(i));
                }
            }
        }

        List<SusbTimeIndex> susbTimeIndices = Lists.newArrayList();
        //按照设备分组
        Map<Long, List<SusbTimeIndex>> collect3 = susbTimeIndicesFirst.stream().collect(Collectors.groupingBy(su -> su.getDeviceId()));
        // 设备和最新启动时间
        Map<Long, SusbTimeIndex> lastStartMap = Maps.newHashMap();
        collect3.forEach((k,v)->{
            for (int i = 0; i < v.size(); i++) {
                SusbTimeIndex dto = OrikaMapperFactory.getMapper().map(v.get(i), SusbTimeIndex.class);

                ZonedDateTime start = null;
                ZonedDateTime end = null;
                if(v.get(i).getType()==1){
                    if(i==0){
                        ZoneId zoneId = ZoneId.of("UTC+1");
                        start = ZonedDateTime.of(v.get(i).getStartTime().getYear(),1,1,00,00,00,000,zoneId);
                        end = v.get(i).getStartTime();
                    }else{
                        start = v.get(i-1).getStopTime();
                        end = v.get(i).getStartTime();
                    }
                    dto.setStartTime(start);
                    dto.setStopTime(end);
                    susbTimeIndices.add(dto);
                }
            }
            if(v.get(v.size()-1).getType()==0){
                ZoneId zoneId = ZoneId.of("UTC+1");
                ZonedDateTime start = v.get(v.size()-1).getStopTime();
                ZonedDateTime end = null;
                // 到目前是否还在运行
                if(v.get(v.size()-1).getStopTime().getYear()==LocalDate.now().getYear()){
                    end = ZonedDateTime.of(LocalDateTime.now(),zoneId);
                } else {
                    end =  ZonedDateTime.of(v.get(v.size()-1).getStopTime().getYear(),12,31,23,59,59,000,zoneId);
                }
                SusbTimeIndex lastone = OrikaMapperFactory.getMapper().map(v.get(v.size()-1), SusbTimeIndex.class);
                lastone.setStartTime(start);
                lastone.setStopTime(end);
                susbTimeIndices.add(lastone);
                // 缓存最近启动时间
                lastStartMap.put(k,lastone);
            }
        });

        // 按照年份分组
        Map<Integer,Map<Integer, List<SusbTimeIndex>>> datas = Maps.newHashMap();
        Map<Integer,Map<Integer, Map>> result = Maps.newHashMap();
        //筛选出开始结束不跨年的数据，并且按照年份分组
        Map<Integer, List<SusbTimeIndex>> collect = susbTimeIndices.parallelStream().filter(s ->
                s.getStartTime().getYear() == s.getStopTime().getYear()
        ).collect(Collectors.groupingBy(su -> su.getStartTime().getYear()));

        //筛选出跨年份的数据
        Map<Integer, List<SusbTimeIndex>> diff = susbTimeIndices.stream().filter(s ->
            s.getStartTime().getYear()!=s.getStopTime().getYear()
        ).collect(Collectors.groupingBy(su -> su.getStartTime().getYear()));

        // 拆分时间段加入对应年份中
        diff.forEach((k,v)->{
            v.forEach(s->{
                ZoneId zoneId = ZoneId.of("UTC+1");
//                ZonedDateTime zonedDateTimeStop = ZonedDateTime.of(s.getStartTime().getYear(),12,31,23,59,59,000,zoneId);
//                ZonedDateTime stopTime = s.getStopTime();
//                s.setStopTime(zonedDateTimeStop);
//                collect.get(k).add(s);

                ZonedDateTime zonedDateTimeStopPre = ZonedDateTime.of(s.getStartTime().getYear(),12,31,23,59,59,000,zoneId);
                SusbTimeIndex susbTimeIndexPre =  OrikaMapperFactory.getMapper().map(s, SusbTimeIndex.class);
                susbTimeIndexPre.setStartTime(s.getStartTime());
                susbTimeIndexPre.setStopTime(zonedDateTimeStopPre);
                List<SusbTimeIndex> afterHalfPre = collect.getOrDefault(k,new ArrayList<SusbTimeIndex>());
                afterHalfPre.add(susbTimeIndexPre);
                collect.put(k,afterHalfPre);

                ZonedDateTime zonedDateTimeStart = ZonedDateTime.of(s.getStartTime().getYear()+1,1,1,00,00,00,000,zoneId);
                SusbTimeIndex susbTimeIndex2 = OrikaMapperFactory.getMapper().map(s, SusbTimeIndex.class);
                susbTimeIndex2.setStartTime(zonedDateTimeStart);
                susbTimeIndex2.setStopTime(s.getStopTime());
                List<SusbTimeIndex> afterHalf = collect.getOrDefault((k+1),new ArrayList<SusbTimeIndex>());
                afterHalf.add(susbTimeIndex2);
                collect.put((k+1),afterHalf);
            });
        });

        // 按照月份分组
        collect.forEach((k,v)->{
            //筛选出开始结束不跨月的数据，并且按照月份分组
            Map<Integer, List<SusbTimeIndex>> collectMonth = v.parallelStream().filter(s ->
                    s.getStartTime().getMonthValue() == s.getStopTime().getMonthValue()
            ).collect(Collectors.groupingBy(su -> su.getStartTime().getMonthValue()));


            //筛选出跨年份的数据
            Map<Integer, List<SusbTimeIndex>> diffMonth = v.parallelStream().filter(s ->
                    s.getStartTime().getMonthValue()!=s.getStopTime().getMonthValue()
            ).collect(Collectors.groupingBy(su -> su.getStartTime().getMonthValue()));

            // 拆分时间段加入对应月份中
            diffMonth.forEach((k1,v1)->{
                v1.forEach(s->{
                    ZoneId zoneId = ZoneId.of("UTC+1");
                    ZonedDateTime zonedDateTimeStop = ZonedDateTime.of(s.getStartTime().getYear(),s.getStartTime().getMonthValue()+1,1,00,00,00,000,zoneId);
                    SusbTimeIndex susbTimeIndex1 = OrikaMapperFactory.getMapper().map(s, SusbTimeIndex.class);
                    susbTimeIndex1.setStartTime(s.getStartTime());
                    susbTimeIndex1.setStopTime(zonedDateTimeStop);
                    List<SusbTimeIndex> currentMonth =  collectMonth.getOrDefault(s.getStartTime().getMonthValue(), Lists.newArrayList());
                    currentMonth.add(susbTimeIndex1);
                    collectMonth.put(s.getStartTime().getMonthValue(),currentMonth);
                    for(int j=s.getStartTime().getMonthValue()+1;j<s.getStopTime().getMonthValue();j++){
                        ZonedDateTime zonedDateTimeStartMiddle = ZonedDateTime.of(s.getStartTime().getYear(),j,1,00,00,00,000,zoneId);
                        ZonedDateTime zonedDateTimeStopMiddle = ZonedDateTime.of(s.getStartTime().getYear(),(j+1),1,00,00,00,000,zoneId);
                        SusbTimeIndex susbTimeIndex2 = OrikaMapperFactory.getMapper().map(s, SusbTimeIndex.class);
                        susbTimeIndex2.setStartTime(zonedDateTimeStartMiddle);
                        susbTimeIndex2.setStopTime(zonedDateTimeStopMiddle);
                        List<SusbTimeIndex> afterHalf = collectMonth.getOrDefault(j,Lists.newArrayList());
                        afterHalf.add(susbTimeIndex2);
                        collectMonth.put((j),afterHalf);
                    }

                    ZonedDateTime zonedDateTimeStart = ZonedDateTime.of(s.getStartTime().getYear(),s.getStopTime().getMonthValue(),1,00,00,00,000,zoneId);
                    SusbTimeIndex susbTimeIndex2 = OrikaMapperFactory.getMapper().map(s, SusbTimeIndex.class);
                    susbTimeIndex2.setStartTime(zonedDateTimeStart);
                    susbTimeIndex2.setStopTime(s.getStopTime());
                    List<SusbTimeIndex> afterHalf = collectMonth.getOrDefault(s.getStopTime().getMonthValue(),Lists.newArrayList());
                    afterHalf.add(susbTimeIndex2);
                    collectMonth.put(s.getStopTime().getMonthValue(),afterHalf);
                });
            });
            datas.put(k,collectMonth);
        });

        DeviceCond cond = new DeviceCond();
        cond.setCustomerId(customerId);
        cond.setIsRoot(Constant.YES);
        List<DeviceDTO> deviceDTOs = deviceService.selectDeviceByCustomer(cond);
        List<Long> collect2 = deviceDTOs.stream().map(DeviceDTO::getId).collect(Collectors.toList());
        // 计算时长
        datas.forEach((k,v)->{
            Map map2 = Maps.newHashMap();
            v.forEach((k1,v1)->{
                v1.forEach(s->{
                    double second = (double)Duration.between(s.getStartTime().toLocalDateTime(), s.getStopTime().toLocalDateTime()).toMillis();
                    s.setHours(second/(60*60)/1000);
                    s.setDays(second/(60*60)/1000/24);
                });
                double hours = v1.stream().mapToDouble(SusbTimeIndex::getHours).sum();
                double days = v1.stream().mapToDouble(SusbTimeIndex::getDays).sum();
                Map map = Maps.newHashMap();
                map.put("datas",v1);
                map.put("hours",new java.text.DecimalFormat("0.00").format(hours));
                map.put("days",new java.text.DecimalFormat("0.00").format(days));
                // 按照设备分组
                Map<Long, List<SusbTimeIndex>> collect1 = v1.stream().collect(Collectors.groupingBy(SusbTimeIndex::getDeviceId));

                List devices = Lists.newArrayList();
                for (int i = 0; i < collect2.size(); i++) {
                    Map device = Maps.newHashMap();
                    List<SusbTimeIndex> susbTimeIndices1 = collect1.get(collect2.get(i));
                    device.put("deviceId",deviceDTOs.get(i).getId());
                    device.put("deviceNo",deviceDTOs.get(i).getDeviceNo());
                    device.put("deviceName",deviceDTOs.get(i).getName());
                    if(susbTimeIndices1 == null){
                        device.put("hours",0);
                        device.put("days",0);
                        device.put("datas",Lists.newArrayList());
                    }else{
                        double deviceHours = collect1.get(collect2.get(i)).stream().mapToDouble(SusbTimeIndex::getHours).sum();
                        double deviceDays = collect1.get(collect2.get(i)).stream().mapToDouble(SusbTimeIndex::getDays).sum();
                        device.put("hours",new java.text.DecimalFormat("0.00").format(deviceHours));
                        device.put("days",new java.text.DecimalFormat("0.00").format(deviceDays));
                        device.put("datas",susbTimeIndices1);
                        if(lastStartMap.get(deviceDTOs.get(i).getId()) != null) {
                            device.put("startTimeLast",lastStartMap.get(deviceDTOs.get(i).getId()).getStartTime().format(DateFormatterUtil.dateTimeFormatter));
                        }
                    }
                    devices.add(device);
                }
                map.put("devices",devices);
                map2.put(k1,map);
            });
            result.put(k,map2);
        });

        return result;
    }

    /**
     * 设备当年的启机次数
     * @param deviceId
     * @return
     */
    public long susbNum(Long deviceId,Integer year){
        if(year == null){
           year = LocalDate.now().getYear();
        }
        SusbTimeIndex susbTimeIndex = new SusbTimeIndex();
        susbTimeIndex.setDeviceId(deviceId);
        susbTimeIndex.setYear(year);
        List<SusbTimeIndex> susbTimeIndices = susbTimeIndexMapper.selectSusb(susbTimeIndex);
        return susbTimeIndices.size();
    }

}
